//
//  E7Logic.cpp
//  EndlessBattle
//
//  Created by cc on 12-3-17.
//  Copyright (c) 2012年 PalmGame. All rights reserved.
//

#include "E7Logic.h"

#include "E7StageData.h"

CE7Logic* s_pLogic = NULL ;

CE7Logic::CE7Logic():
create_unit_count(0),
delete_unit_count(0),
create_town_count(0),
delete_town_count(0)
{
    m_pActiveMap = NULL ; //new CE7Map() ;
    m_pRule = new CE7Rule();
    m_nMapIndex = -1 ;
    m_bIsActived = false ;
    m_nTurnID = -1 ;
    m_nTurnCount = 0 ;
    m_bIsGameEnd = false ;

    srand((unsigned int)time(NULL)) ;
    
    m_pStageData = NULL ;

    // render info.
    s_pSelect = NULL ;
    s_bIsRedraw = false ;
    s_bIsUpdateInfo = false ;
    s_eCreateUV = UV_NONE ;
    s_eSelectUV = UV_NONE ;
    s_eSelUnitID = -1 ;
    s_nGold = 0 ;
    s_nInGold = 0 ;
    s_nSoldierCount = 0 ;
    s_nSoldierSub = 0 ;
    s_nTowerCount = 0 ;
    s_nTowerSub = 0 ;
    s_bIsBalance = false ;

    m_nStageCount = CE7StageData::GetStageData()->GetMapCount() ;

    if (0 < m_nStageCount)
    {
        m_bIsFirst = false ;
    }
    else
    {
        m_bIsFirst = true ;
    }
}

CE7Logic::~CE7Logic()
{
    m_listUnit.clear() ;
    m_listTown.clear() ;
    m_listCountry.clear() ;
    m_listRobot.clear() ;
    SAFE_DELETE(m_pRule) ;

    SAFE_DELETE(m_pStageData) ;

    SAFE_DELETE(m_pActiveMap) ;
}

void CE7Logic::CreateMap()
{
    if (m_nStageCount >= STAGE_COUNT)
    {
        printf("save map count: [%d] [%d]\n", m_nStageCount, CE7StageData::GetStageData()->GetMapCount()) ;
        return ;
    }

    int stageindex = m_nStageCount ;
    CE7Map* pMap = new CE7Map() ;
    
    printf(" ==== CE7Logic::CreateMap [%d]\n", stageindex) ;
//    if (!pMap->Create(stageindex, (stageindex/6)))
    if (!pMap->Create(stageindex, 0))
    {
        printf("logic create map error : [%d]\n", m_nStageCount) ;
        return ;
    }

    m_pActiveMap = pMap ;
    if (!InitLogicData())
    {
        SAFE_DELETE(pMap) ;
        return ;
    }

    // set save map data.
    m_pActiveMap->SetSaveMapData() ;
    m_pActiveMap->SaveToUserDefault() ;
    m_pActiveMap = NULL ;
    SAFE_DELETE(pMap) ;

    ++m_nStageCount ;
    printf("save map count ===== ===== ===== ===== [%d] [%d]\n", m_nStageCount, CE7StageData::GetStageData()->GetMapCount()) ;
}

void CE7Logic::CreateStartMap()
{
    printf("CE7Logic::CreateStartMap [%d][%d][%d]\n", m_nGameMode, m_nMapIndex, m_nCustomMapID) ;
    s_bIsRestart = false ;
    if (0 == m_nGameMode) // Normal Mode.
    {
        int   mapid = 0 ;
        char* mapname = NULL ;
        int   mapsize = 0 ;
        int*  pData = NULL ;
        
        //    m_nMapIndex++ ;
        
        CE7StageData::GetStageData()->LoadMapData(m_nMapIndex, mapid, mapname, mapsize, &pData) ;
        SAFE_DELETE(m_pActiveMap) ;
        m_pActiveMap = new CE7Map() ;
        if (!m_pActiveMap->Create(m_nMapIndex, mapid, mapsize, pData))
        {
            printf("create map with userdefault : [%d][%d][%s][%d] error\n", m_nMapIndex, mapid, mapname, mapsize) ;
            return ;
        }

        InitLogicData() ;
        m_nTurnID = 0 ; // user first.
        m_nTurnCount = 1 ;
        m_bIsGameEnd = false ;
    }
    else if (1 == m_nGameMode) // Custom Mode.
    {
        SAFE_DELETE(m_pActiveMap) ;
        m_pActiveMap = new CE7Map() ;
        if (!m_pActiveMap->Create(0, m_nCustomMapID))
        {
            printf("logic create map error : [%d]\n", m_nCustomMapID) ;
            return ;
        }
        
        InitLogicData() ;
        m_nTurnID = 0 ; // user first.
        m_nTurnCount = 1 ;
        m_bIsGameEnd = false ;
        
        // set save map data.
        m_pActiveMap->SetSaveMapData() ;
    }
}

bool CE7Logic::InitLogicData()
{
    m_listUnit.clear() ;
    m_listTown.clear() ;
    m_listCountry.clear() ;
    m_listRobot.clear() ;

    create_unit_count = 0 ;
    delete_unit_count = 0 ;
    create_town_count = 0 ;
    delete_town_count = 0 ;

    CELL_INFO_LIST::iterator itr ;
    CELL_ID_LIST::iterator itr_a ;
    CE7Cell* pCell = NULL ;

    // init all countrys.
    printf("add countrys ... start ...[%lu] [%d]\n", m_listCountry.size(), m_pActiveMap->GetCountryCount()) ;
    int country_count = m_pActiveMap->GetCountryCount() ;
    for (int i = 0; i < country_count; ++i)
    {
        CE7Country* pNew = new CE7Country() ;
        pNew->InitData(i) ;
        m_listCountry.push_back(pNew) ;

        if (0 < i)
        {
            CE7Robot* pRobot = new CE7Robot() ;
            pRobot->Create(i, false) ;
            m_listRobot.push_back(pRobot) ;
        }

        // add cells, add temp town start cell id.
        CELL_ID_LIST tempcelllist ;
        tempcelllist.clear() ;
//        printf("m_pActiveMap->m_listCells size: [%lu]\n", m_pActiveMap->m_listCells.size()) ;
        for (itr = m_pActiveMap->m_listCells.begin(); itr != m_pActiveMap->m_listCells.end(); ++itr)
        {
            pCell = (*itr) ;
            if (i != pCell->GetCountryID())
            {
                continue ;
            }

            pNew->AddCell(pCell->GetID()) ;
            for (int j = 0; j < 6; ++j)
            {
                if (pCell->GetNeighborPointer(j) && pCell->GetNeighborPointer(j)->GetCountryID() == pCell->GetCountryID())
                {
                    tempcelllist.push_back(pCell->GetID()) ; // set temp cell list.
                    break ;
                }
            }
        }

        // set cell's town id.
        SetCellTownID(i, tempcelllist) ;
    }
    printf("add countrys ... end ...[%lu] [%lu]\n", m_listCountry.size(), m_listRobot.size()) ;

    printf("town count: [%lu]\n", m_listTown.size()) ;

    if (0 >= m_listTown.size())
    {
        return false ;
    }

    // add cell to towns.
    TOWN_INFO_LIST::iterator itr_town ;
    CE7Town* pTown = NULL ;
    for (itr_town = m_listTown.begin(); itr_town != m_listTown.end(); ++itr_town)
    {
        pTown = (*itr_town) ;
        for (itr = m_pActiveMap->m_listCells.begin(); itr != m_pActiveMap->m_listCells.end(); ++itr)
        {
            if (pTown->GetID() == (*itr)->GetTownID())
            {
                pTown->AddCell((*itr)->GetID()) ;
            }
        }
    }

    // add city to towns.
    if (m_pActiveMap->IsLoadMap())
    {
        int uv = 0 ;
        int* pTempData = m_pActiveMap->GetLoadData() ;
        for (int i = 0; i < m_pActiveMap->GetCellCount(); ++i)
        {
            uv = (int)(pTempData[i]%100) ;
//            printf("add city to towns ---- [%d][%d][%d]\n", i, uv, pTempData[i]) ;
            if (UV_NONE < uv)
            {
                pCell = m_pActiveMap->GetSelectCellInfo(i) ;
                if (NULL == pCell)
                {
                    continue ;
                }
                if (-1 == pCell->GetCountryID())
                {
                    continue ;
                }
                if (-1 == pCell->GetTownID())
                {
                    continue ;
                }
                pTown = GetSelectTownInfo(pCell->GetTownID()) ;

                CE7Unit* pUnit = new CE7Unit() ;
                pUnit->Create(m_listUnit.size(), (eUnitValue)uv, pCell->GetCountryID(), pCell->GetTownID(), pCell->GetID()) ;
                AddUnitInfo(pUnit) ;

                pCell->SetUnitID(pUnit->GetID()) ;
                pCell->SetUV(pUnit->GetUV()) ;
                pTown->AddUnit(pUnit->GetID()) ;
            }
        }
    }
    else
    {
        CELL_ID_LIST::iterator itr_cellid ;
        int tcount, tindex ;
        for (itr_town = m_listTown.begin(); itr_town != m_listTown.end(); ++itr_town)
        {
            pTown = (*itr_town) ;
            tindex = 0 ;
            tcount = pTown->m_listCellIDs.size()/2 ;
            for (itr_cellid = pTown->m_listCellIDs.begin(); tindex < tcount; ++itr_cellid, ++tindex) ;
            for (itr = m_pActiveMap->m_listCells.begin(); itr != m_pActiveMap->m_listCells.end(); ++itr)
            {
                pCell = (*itr) ;
                if ((*itr_cellid) == pCell->GetID())
                {
                    CE7Unit* pUnit = new CE7Unit() ;
                    pUnit->Create(m_listUnit.size(), UV_CITY, pCell->GetCountryID(), pCell->GetTownID(), pCell->GetID()) ;
                    AddUnitInfo(pUnit) ;
                    
                    pCell->SetUnitID(pUnit->GetID()) ;
                    pCell->SetUV(pUnit->GetUV()) ;
                    pTown->AddUnit(pUnit->GetID()) ;
                    
//                    for (int i = 0; i < 6; ++i)
//                    {
//                        if (NULL != pCell->GetNeighborPointer(i) &&
//                            pCell->GetCountryID() == pCell->GetNeighborPointer(i)->GetCountryID())
//                        {
//                            pCell->GetNeighborPointer(i)->SetUV(pCell->GetUV()) ;
//                        }
//                    }
                    
                    break ;
                }
            }
        }
    }

    for (CELL_INFO_LIST::iterator itr_cellinfo = m_pActiveMap->m_listCells.begin(); itr_cellinfo != m_pActiveMap->m_listCells.end(); ++itr_cellinfo)
    {
//        printf("cell info: [%d]\n", (*itr_cellinfo)->GetUnitID()) ;
        (*itr_cellinfo)->UpdateUV() ;
    }

    // compute golds to towns and add town to country.
    for (itr_town = m_listTown.begin(); itr_town != m_listTown.end(); ++itr_town)
    {
        (*itr_town)->BalanceInit() ;
//        printf("town balance init : [%d] [%d][%d]\n", (*itr_town)->GetID(),
//               (*itr_town)->GetGold(), (*itr_town)->GetInGold()) ;
    }

    m_nTownSize = m_listTown.size() ;
    m_nUnitSize = m_listUnit.size() ;

    m_bIsActived = true ;

    m_nTurnID = -1 ;

    for (itr_town = m_listTown.begin(); itr_town != m_listTown.end(); ++itr_town)
    {
        if ((*itr_town)->GetCountryID() == 0)
        {
            return true ;
        }
    }

    printf("no user's town!\n") ;
    return false ;
}

void CE7Logic::FindAllWithCell(CE7Cell* pStart)
{
    for (int i = 0; i < 6; ++i)
    {
        if (NULL != pStart->GetNeighborPointer(i) &&
            -1 == pStart->GetNeighborPointer(i)->GetTownID() &&
            pStart->GetCountryID() == pStart->GetNeighborPointer(i)->GetCountryID())
        {
            pStart->GetNeighborPointer(i)->SetTownID(pStart->GetTownID()) ;
            FindAllWithCell(pStart->GetNeighborPointer(i)) ;
        }
    }
}

void CE7Logic::SetCellTownID(int countryid, CELL_ID_LIST tlist)
{
    CELL_ID_LIST::iterator itr ;
    CE7Cell* pCell = NULL ;
    for (itr = tlist.begin(); itr != tlist.end(); ++itr)
    {
        pCell = m_pActiveMap->GetSelectCellInfo(*itr) ;
        if (NULL == pCell)
        {
            printf("error AddCellToTown : [%d] [%d]\n", countryid, (*itr)) ;
            return ;
        }

        if (-1 == pCell->GetTownID())
        {
            CE7Town* pNew = new CE7Town() ;
            pNew->InitData(m_listTown.size(), countryid, 0) ;
            AddTownInfo(pNew) ;

            pCell->SetTownID(pNew->GetID()) ;
            FindAllWithCell(pCell) ;
        }
    }
}

bool CE7Logic::Loop()
{
    if (-1 == m_nTurnID)
    {
        return false ;
    }

    if (0 == m_nTurnID)
    {
        return false ;
    }

    for (ROBOT_INFO_LIST::iterator itr = m_listRobot.begin(); itr != m_listRobot.end(); ++itr)
    {
        if ((*itr)->GetID() == m_nTurnID)
        {
            printf("enter robot id :[%d] is process [%lu]\n", m_nTurnID, m_listRobot.size()) ;
            sleep(1) ;
            (*itr)->Process() ;
            ++m_nTurnID ;

            // check results.
            if (s_pLogic->GetRule()->CheckGameEnd())
            {
                SetGameEnd() ;
                return true ;
            }

            // set to user turn.
            if ((m_listRobot.size()+1) <= m_nTurnID)
            {
                s_bIsBalance = true ;
                // set UV_TREE's neighbor cell to UV_TREE.
                CELL_ID_LIST tlist ;
                for (UNIT_INFO_LIST::iterator itr_unit = m_listUnit.begin(); itr_unit != m_listUnit.end(); ++itr_unit)
                {
                    if (UV_TREE == (*itr_unit)->GetUV())
                    {
                        tlist.push_back((*itr_unit)->GetCellID()) ;
                    }
                }
//                for (CELL_ID_LIST::iterator itr_cellid = tlist.begin(); itr_cellid != tlist.end(); ++itr_cellid)
//                {
//                    CE7Cell* pTree = m_pActiveMap->GetSelectCellInfo(*itr_cellid) ;
//                    if (NULL == pTree)
//                    {
//                        continue ;
//                    }
//                    if (-1 == pTree->GetCountryID())
//                    {
//                        continue ;
//                    }
//                    for (int i = 0; i < 6; ++i)
//                    {
//                        CE7Cell* pNeighbor = pTree->GetNeighborPointer(i) ;
//                        if (NULL == pNeighbor)
//                        {
//                            continue ;
//                        }
//                        if (-1 == pNeighbor->GetCountryID())
//                        {
//                            continue ;
//                        }
//                        if (-1 == pNeighbor->GetUnitID())
//                        {
//                            // add random.
//                            if (0 != pNeighbor->GetCountryID())
//                            {
//                                continue ;
//                            }
//                            CE7Unit* pNewTree = new CE7Unit() ;
//                            pNewTree->Create(GetNewUnitID(), UV_TREE, pNeighbor->GetCountryID(), pNeighbor->GetTownID(), pNeighbor->GetID()) ;
//                            AddUnitInfo(pNewTree) ;
//                            pNeighbor->SetUnitID(pNewTree->GetID()) ;
//                            if (-1 != pNeighbor->GetTownID())
//                            {
//                                CE7Town* pNeighborTown = GetSelectTownInfo(pNeighbor->GetTownID()) ;
//                                if (NULL != pNeighborTown)
//                                {
//                                    pNeighborTown->AddUnit(pNewTree->GetID()) ;
//                                }
//                            }
//                        }
//                    }
//                }
                // set UV_DEAD to UV_NONE.
                for (UNIT_INFO_LIST::iterator itr_unit = m_listUnit.begin(); itr_unit != m_listUnit.end(); ++itr_unit)
                {
                    if (UV_DEAD == (*itr_unit)->GetUV())
                    {
                        (*itr_unit)->SetUV(UV_TREE) ;
                    }
                }
                // balance all towns.
                for (TOWN_INFO_LIST::iterator itr_town = m_listTown.begin(); itr_town != m_listTown.end(); ++itr_town)
                {
                    (*itr_town)->Balance() ;
                }
                // set all units action.
                for (UNIT_INFO_LIST::iterator itr_unit = m_listUnit.begin(); itr_unit != m_listUnit.end(); ++itr_unit)
                {
                    (*itr_unit)->ResetAction() ;
                }
                // update all cell unitvalue.
                for (CELL_INFO_LIST::iterator itr_cell = m_pActiveMap->m_listCells.begin(); itr_cell != m_pActiveMap->m_listCells.end(); ++itr_cell)
                {
                    (*itr_cell)->UpdateUV() ;
                }
                if (s_bPlaySound)
                {
                    SimpleAudioEngine::sharedEngine()->playEffect(sound_money) ;
                }

                m_nTurnID = 0 ;
                ++m_nTurnCount ;
                s_bIsBalance = false ;
            }

            printf("exit robot process ===== \n") ;
            return true ;
        }
    }

    return true ;
}

bool CE7Logic::AddUnitInfo(CE7Unit* pUnit)
{
    for (UNIT_INFO_LIST::iterator itr = m_listUnit.begin(); itr != m_listUnit.end(); ++itr)
    {
        if ((*itr)->GetID() == pUnit->GetID())
        {
            printf("CE7Logic::AddUnitInfo ERROR [%d]\n", pUnit->GetID()) ;
            return false ;
        }
    }

    m_listUnit.push_back(pUnit) ;
    return true ;
}

bool CE7Logic::AddTownInfo(CE7Town* pTown)
{
    for (TOWN_INFO_LIST::iterator itr = m_listTown.begin(); itr != m_listTown.end(); ++itr)
    {
        if ((*itr)->GetID() == pTown->GetID())
        {
            printf("CE7Logic::AddTownInfo ERROR [%d]\n", pTown->GetID()) ;
            return false ;
        }
    }

    m_listTown.push_back(pTown) ;
    return true ;
}

CE7Unit* CE7Logic::GetSelectUnitInfo(int nID)
{
//    printf("CE7Logic::GetSelectUnitInfo m_listUnit.size : [%lu]\n", m_listUnit.size()) ;
    for (UNIT_INFO_LIST::iterator itr = m_listUnit.begin(); itr != m_listUnit.end(); ++itr)
    {
//        printf("CE7Logic::GetSelectUnitInfo [%d] [%d] \n", nID, (*itr)->GetID()) ;
        if ((*itr)->GetID() == nID)
        {
            return (*itr) ;
        }
    }
    return NULL ;
}

bool CE7Logic::DelSelectUnitInfo(int nID)
{
    for (UNIT_INFO_LIST::iterator itr = m_listUnit.begin(); itr != m_listUnit.end(); ++itr)
    {
        if ((*itr)->GetID() == nID)
        {
            m_listUnit.erase(itr) ;
            return true ;
        }
    }
    return false ;
}

CE7Town* CE7Logic::GetSelectTownInfo(int nID)
{
    for (TOWN_INFO_LIST::iterator itr = m_listTown.begin(); itr != m_listTown.end(); ++itr)
    {
        if ((*itr)->GetID() == nID)
        {
            return (*itr) ;
        }
    }
    return NULL ;
}

bool CE7Logic::DelSelectTownInfo(int nID)
{
    for (TOWN_INFO_LIST::iterator itr = m_listTown.begin(); itr != m_listTown.end(); ++itr)
    {
        if ((*itr)->GetID() == nID)
        {
            (*itr)->Destroy() ;
            m_listTown.erase(itr) ;
            return true ;
        }
    }
    return false ;
}

CE7Country* CE7Logic::GetSelectCountryInfo(int nID)
{
    for (COUNTRY_INFO_LIST::iterator itr = m_listCountry.begin(); itr != m_listCountry.end(); ++itr)
    {
        if ((*itr)->GetID() == nID)
        {
            return (*itr) ;
        }
    }
    return NULL ;
}

//CE7Map* CE7Logic::GetSelectMapInfo(int nID)
//{
//    for (MAP_INFO_LIST::iterator itr = m_listMap.begin(); itr != m_listMap.end(); ++itr)
//    {
//        if ((*itr)->GetID() == nID)
//        {
//            return (*itr) ;
//        }
//    }
//
//    return NULL ;
//}

CE7Robot* CE7Logic::GetSelectRobotInfo(int nID)
{
    for (ROBOT_INFO_LIST::iterator itr = m_listRobot.begin(); itr != m_listRobot.end(); ++itr)
    {
        if ((*itr)->GetID() == nID)
        {
            return (*itr) ;
        }
    }

    return NULL ;
}























